package com.jvup.common.support.base;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.FragmentActivity;

import com.jvup.common.utils.ObserveBinderHelper;
import com.qire.antscore.annotation.DalExceptionObserve;

/**
 * 项目内基础Activity，提供一些统一行为
 * @param <B> viewDataBinder 具体类型
 */
public abstract class BaseActivity<B extends ViewDataBinding> extends FragmentActivity {

    /**
     * viewDataBinder 提供一个页面中View与Data的绑定器，是一个存放 UI（View） 和 Data（model行为）等关联的容器，
     * 并协助完成关联绑定和双向通知观察者，该对象会在第一次调用 {@link #viewDataBinder()} 时完成初始化，一般在 {@link #onCreate onCreate()} 时创建。
     */
    private B viewDataBinder;

    /**
     * Activity 页面使用的布局资源ID，期望在每个继承 Activity 中指定，该ID会用来参与 {@link #viewDataBinder()} 的构建，已完成指定的页面构建。
     * @return 页面的布局资源ID
     */
    public abstract int layoutRid();

    /**
     * 获得 viewDataBinder 容器，如果页面没有 viewDataBinder 则完成页面绑定，否则直接返回已有实体。
     * 该方法替代了 {@link #setContentView setContentView()} 方法，
     * 使用从 {@link #layoutRid layoutRid()} 方法提供的布局ID完成布局加载，只在首次调用时加载布局，该方法是线程安全的。
     * @return {@link ViewDataBinding} viewDataBinder 视图数据绑定器，对于页面 View 或 Model 使用应该尽可能使用该方法来操作
     */
    public synchronized B viewDataBinder() {
        if(null == viewDataBinder) {
            viewDataBinder = DataBindingUtil.setContentView(this, layoutRid());
            viewDataBinder.setLifecycleOwner(this);
        }
        return viewDataBinder;
    }

    /**
     * 提供一个检查判定当前页面是否侵入状态栏占满全屏，目前主要配合顶部小吃栏样式提示使用。
     * 也可提供给其他需要判断当前Activity页面是否侵入全屏作为判断。
     * 在具体实现的 Activity 中应该可以确定当前页面是否全屏，在有需要提供全屏判断的页面应该继承重写该方法。
     * @return true 为侵入全屏否则为 false
     */
    public boolean isFullScreen() {
        return true;
    }

    /**
     * 页面其他辅助功能关联观察者注册方法，该方法会在{@link #onCreate onCreate()}方法中调用，
     * 默认实现了对于 Dal 访问 http API 请求时异常捕获处理的方法，
     * 通过注解{@link DalExceptionObserve}修饰进过APT自动生成的注册代码关联调用，
     * 如果有其他需要注册和关联的逻辑应该尽可能继承重写并追加新的注册逻辑，
     * 由于在onCreate等生命周期方法中可能影响UI线程的handle循环，有可能会在底层统一优化处理，尽可能写在这里便于优化。<br />
     * 该方法应该与 {@link #unregisterObserver unregisterObserver()}方法成对出现，注册也需注销
     */
    protected void registerObserver() {
        ObserveBinderHelper.callRegisterOfDalExceptionObserveBinder(this);
    }

    /**
     * 页面其他辅助功能关联观察者注销方法，该方法会在{@link #onDestroy onDestroy()}方法中调用，
     * 默认实现了对于 Dal 访问 http API 请求时异常捕获处理的方法，
     * 通过注解{@link DalExceptionObserve}修饰进过APT自动生成的注销代码关联调用，
     * 如果有其他需要注销和解绑关联的逻辑应该尽可能继承重写并追加新的注销逻辑，
     * 由于在onDestroy等生命周期方法中可能影响UI线程的handle循环，有可能会在底层统一优化处理，尽可能写在这里便于优化。<br />
     * 该方法应该与 {@link #registerObserver registerObserver()}方法成对出现，注册也需注销
     */
    protected void unregisterObserver() {
        ObserveBinderHelper.callUnregisterOfDalExceptionObserveBinder(this);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewDataBinder();
        registerObserver();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterObserver();
    }

}
